package br.com.tcc.systemdx.database;

import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Arrays;

import javax.sql.DataSource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class DatabaseMigration {
	private static final Log log = LogFactory.getLog(DatabaseMigration.class);

	@Autowired
	private DataSource dataSource;

	public void atualizarBancoDeDados() throws Exception {

		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;

		try {
			conn = dataSource.getConnection();
			stmt = conn.createStatement();
			try {
				stmt.executeUpdate("CREATE TABLE migrations ("
						+ "  data TIMESTAMP,        "
						+ "  arquivo VARCHAR(63),   "
						+ "  erros TEXT             "
						+ ");                       ");
			} catch (SQLException e) {
				log.info("SQLException " + e.getMessage());
			}

			File directory = new File(
					"src/main/database/mysql/changes");
			if (directory.isDirectory()) {
				File file = null;
				conn.setAutoCommit(false);
				
				String[] files = directory.list();
				Arrays.sort(files);
				for (String name : files) {
					file = new File(directory.getPath() + "/" + name);
					if (file.isFile()) {

						rs = stmt
								.executeQuery("SELECT arquivo FROM migrations");

						boolean estaNaTabela = false;
						while (rs.next()) {
							if (name.equals(rs.getString("arquivo")))
								estaNaTabela = true;
						}

						Timestamp now = new Timestamp(java.lang.System
								.currentTimeMillis());

						if (!estaNaTabela) {
							try {
								stmt.executeUpdate(FileUtils
										.readFileToString(file));
								stmt
										.executeUpdate("INSERT INTO migrations (data, arquivo) "
												+ "VALUES ('"
												+ now
												+ "', '"
												+ name + "');");
								conn.commit();
							} catch (SQLException e) {
								conn.rollback();
								log.error("Erro executando o arquivo: " + name,
										e);
								stmt
										.executeUpdate("INSERT INTO migrations (data, arquivo, erros) "
												+ "VALUES ('"
												+ now
												+ "', '"
												+ name
												+ "', '"
												+ e.getMessage() + "');");
								conn.commit();
							}
						}

					}
				}
				conn.setAutoCommit(true);
			}

		} finally {
			if (rs != null)
				try {
					rs.close();
				} catch (Throwable t) {
				}
			if (stmt != null)
				try {
					stmt.close();
				} catch (Throwable t) {
				}
			if (conn != null)
				try {
					conn.close();
				} catch (Throwable t) {
				}

		}
	}
	
	
	/**
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		log.info("==== Carregando contexto spring ============================");
		GenericApplicationContext ctx = new GenericApplicationContext();
		new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
		BeanDefinition thisBeanDefinition = new RootBeanDefinition(DatabaseMigration.class);
		ctx.registerBeanDefinition("databaseMigration", thisBeanDefinition);
		ctx.refresh();
		log.info("==== Contexto spring carregado ==============================");
		
		DatabaseMigration databaseMigrationBean = (DatabaseMigration) ctx.getBean("databaseMigration");

		log.info("==== Iniciando migração =======================================");
		databaseMigrationBean.atualizarBancoDeDados();
		log.info("==== Migração finalizada ======================================");
		log.info("==== Parando o contexto =======================================");
		ctx.stop();
		
	}
}
